﻿// 3587. 连通图.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <memory.h>

using namespace std;
/*
https://www.acwing.com/problem/content/3590/

给定一个无向图和其中的所有边，判断这个图是否所有顶点都是连通的。

输入格式
输入包含若干组数据。

每组数据第一行包含两个整数 n和 m，表示无向图的点和边数。

接下来 m行，每行包含两个整数 x,y，表示点 x 和点 y 相连。

点的编号从 1到 n。

图中可能存在重边和自环。

输出格式
每组数据输出一行，一个结果，如果所有顶点都是连通的，输出 YES，否则输出 NO。

数据范围
输入最多包含 10 组数据。
1≤n≤1000
,
1≤m≤5000
,
1≤x,y≤n
输入样例：
4 3
1 2
2 3
3 2
3 2
1 2
2 3
输出样例：
NO
YES
*/

const int N = 1010;
const int M = 10010;
int f[N]; int vis[N];
int h[N], e[M], ne[M], idx;
int n, m;


void add(int a, int b) {
	e[idx] = b; ne[idx] = h[a]; h[a] = idx++;
}

void init() {
	for (int i = 0; i < N; i++) { f[i] = i; }
	memset(h, -1, sizeof h);
	memset(vis, 0, sizeof vis);
}

int find(int x) {
	if (x != f[x]) {
		f[x] = find(f[x]);
	}

	return f[x];
}

void merge(int a, int b) {
	a = find(a); b = find(b);
	f[a] = b;
}
 

int main()
{
	//while (cin >> n >> m) {
	while(~scanf("%d%d",&n,&m)){
		init();
		for (int i = 0; i < m; i++) {
			int a, b;
			cin >> a >> b;
			merge(a, b);
		}
		int ans = -1; int flag = 1;
		for (int i = 1; i <= n; i++) {
			if (ans == -1) {
				ans = find(f[i]);
			}
			else if (ans != find(f[i])) {
				flag = 0; break;
			}
		}

		if (flag == 1) {
			puts("YES");
		}
		else {
			puts("NO");
		}

		
	}

	

	return 0;
}

 